﻿

import numpy as np

# 创建示例数组
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.arange(10)

print("数组1:\n", arr1)
print("数组2:", arr2)


# 保存单个数组到 .npy 文件
np.save('array1.npy', arr1)

# 从 .npy 文件加载数组
loaded_arr1 = np.load('array1.npy')
print("从文件加载的数组1:\n", loaded_arr1)



# 保存多个数组到 .npz 文件
np.savez('arrays.npz', arr1=arr1, arr2=arr2)

# 从 .npz 文件加载数组
loaded_arrays = np.load('arrays.npz')
print("文件中的数组名称:", loaded_arrays.files)
print("数组1:\n", loaded_arrays['arr1'])
print("数组2:", loaded_arrays['arr2'])

# 使用压缩保存
np.savez_compressed('arrays_compressed.npz', arr1=arr1, arr2=arr2)




# 创建内存映射文件
# 这对于处理大于内存的数据集非常有用
mmap_arr = np.memmap('mmap_array.dat', dtype='float32', mode='w+', shape=(1000, 1000))

# 填充数据
mmap_arr[:] = np.random.random((1000, 1000))

# 执行一些操作
mmap_arr[0, :] = 1.0

# 刷新更改到磁盘
mmap_arr.flush()

# 重新打开内存映射文件
mmap_arr2 = np.memmap('mmap_array.dat', dtype='float32', mode='r', shape=(1000, 1000))
print("内存映射数组的形状:", mmap_arr2.shape)
print("第一行的前5个元素:", mmap_arr2[0, :5])

# 删除内存映射对象和文件
del mmap_arr, mmap_arr2
import os
os.remove('mmap_array.dat')



# 创建示例数据
data = np.array([[1, 2, 3.5], [4, 5.2, 6], [7, 8, 9.8]])

# 保存到 CSV 文件
np.savetxt('data.csv', data, delimiter=',', fmt='%.2f', header='col1,col2,col3')

# 从 CSV 文件加载数据
loaded_data = np.loadtxt('data.csv', delimiter=',', skiprows=1)
print("从CSV加载的数据:\n", loaded_data)

# 处理包含混合数据类型的CSV
# 首先使用genfromtxt查看数据结构
test_data = np.genfromtxt('data.csv', delimiter=',', names=True, dtype=None, encoding=None)
print("结构化数据:\n", test_data)
print("列名:", test_data.dtype.names)

# 使用pandas处理混合类型数据可能更合适，但NumPy也可以处理
mixed_data = np.recfromcsv('data.csv')
print("记录数组:\n", mixed_data)



# 使用自定义格式保存数据
np.savetxt('custom_format.txt', data, 
           fmt='%03d|%.2f|%04.1f', 
           header='整数|浮点数1|浮点数2',
           comments='# ')

# 从自定义格式加载数据
custom_data = np.loadtxt('custom_format.txt', 
                        delimiter='|', 
                        skiprows=1,
                        dtype={'names': ('int_col', 'float1_col', 'float2_col'),
                               'formats': ('i4', 'f4', 'f4')})
print("自定义格式数据:\n", custom_data)

# 使用genfromtxt处理更复杂的格式
complex_data = np.genfromtxt('custom_format.txt',
                            delimiter='|',
                            skip_header=1,
                            dtype=[('int_col', 'i4'), ('float1_col', 'f4'), ('float2_col', 'f4')])
print("复杂格式数据:\n", complex_data)


# 使用 tofile 保存二进制数据
arr1.tofile('binary_data.bin')

# 使用 fromfile 读取二进制数据
# 需要知道数据的类型和形状
loaded_binary = np.fromfile('binary_data.bin', dtype=arr1.dtype)
loaded_binary = loaded_binary.reshape(arr1.shape)
print("从二进制文件加载的数据:\n", loaded_binary)



# 使用文件对象进行IO操作
with open('array_data.bin', 'wb') as f:
    arr1.tofile(f)

with open('array_data.bin', 'rb') as f:
    data_from_file = np.fromfile(f, dtype=arr1.dtype)
    data_from_file = data_from_file.reshape(arr1.shape)
    print("从文件对象加载的数据:\n", data_from_file)

# 使用StringIO进行内存中的文本IO
from io import StringIO
import numpy as np

# 创建文本数据
data_text = "1,2,3\n4,5,6\n7,8,9"

# 使用StringIO作为文件对象
f = StringIO(data_text)
data_from_string = np.loadtxt(f, delimiter=',')
print("从字符串加载的数据:\n", data_from_string)

# 将数据保存到StringIO
output = StringIO()
np.savetxt(output, arr1, delimiter=',')
print("保存到StringIO的内容:", output.getvalue())


# 对于非常大的文件，可以分块处理
def process_large_file(filename, chunk_size=1000):
    """分块处理大型文本文件"""
    results = []
    
    # 使用loadtxt的迭代器功能
    for chunk in np.loadtxt(filename, delimiter=',', skiprows=1, 
                          max_rows=chunk_size, ndmin=2):
        # 处理每个块
        chunk_mean = np.mean(chunk, axis=0)
        results.append(chunk_mean)
    
    return np.array(results)

# 创建大型CSV文件示例
large_data = np.random.rand(10000, 5)
np.savetxt('large_data.csv', large_data, delimiter=',')

# 分块处理
chunk_means = process_large_file('large_data.csv', chunk_size=1000)
print("分块处理结果形状:", chunk_means.shape)


# 创建大型二进制文件
large_binary = np.memmap('large_binary.dat', dtype='float64', mode='w+', shape=(10000, 1000))
large_binary[:] = np.random.rand(10000, 1000)
large_binary.flush()

# 使用内存映射读取部分数据
partial_data = np.memmap('large_binary.dat', dtype='float64', mode='r', shape=(100, 1000))
print("部分数据的形状:", partial_data.shape)
print("部分数据的均值:", np.mean(partial_data))

# 清理
del large_binary, partial_data
import os
os.remove('large_binary.dat')


def data_preprocessing_pipeline(input_file, output_file):
    """数据预处理管道"""
    # 1. 加载数据
    data = np.loadtxt(input_file, delimiter=',', skiprows=1)
    
    # 2. 数据清洗（移除NaN值）
    data = data[~np.isnan(data).any(axis=1)]
    
    # 3. 数据标准化
    mean = np.mean(data, axis=0)
    std = np.std(data, axis=0)
    data_normalized = (data - mean) / std
    
    # 4. 保存处理后的数据
    np.savetxt(output_file, data_normalized, delimiter=',', 
               header='标准化后的数据', comments='# ')
    
    return data_normalized

# 创建示例数据
sample_data = np.random.randn(100, 5)
np.savetxt('raw_data.csv', sample_data, delimiter=',', header='col1,col2,col3,col4,col5')

# 应用预处理管道
processed_data = data_preprocessing_pipeline('raw_data.csv', 'processed_data.csv')
print("处理后的数据形状:", processed_data.shape)




def format_converter(input_file, output_file, input_format, output_format):
    """多种格式数据转换器"""
    if input_format == 'csv':
        data = np.loadtxt(input_file, delimiter=',', skiprows=1)
    elif input_format == 'npy':
        data = np.load(input_file)
    elif input_format == 'binary':
        # 需要知道原始数据的形状和类型
        data = np.fromfile(input_file, dtype=np.float64)
        # 假设是100x5的数组
        data = data.reshape((100, 5))
    else:
        raise ValueError("不支持的输入格式")
    
    if output_format == 'csv':
        np.savetxt(output_file, data, delimiter=',')
    elif output_format == 'npy':
        np.save(output_file, data)
    elif output_format == 'binary':
        data.tofile(output_file)
    else:
        raise ValueError("不支持的输出格式")
    
    return data

# 使用转换器
converted_data = format_converter('raw_data.csv', 'converted_data.npy', 'csv', 'npy')
print("转换后的数据形状:", converted_data.shape)



import time

# 比较不同IO方法的性能
large_array = np.random.rand(10000, 100)

# 测试 .npy 格式
start = time.time()
np.save('test_npy.npy', large_array)
load_time_npy = time.time() - start

start = time.time()
_ = np.load('test_npy.npy')
save_time_npy = time.time() - start

# 测试 .npz 格式（压缩）
start = time.time()
np.savez_compressed('test_npz.npz', data=large_array)
load_time_npz = time.time() - start

start = time.time()
_ = np.load('test_npz.npz')['data']
save_time_npz = time.time() - start

# 测试 CSV 格式
start = time.time()
np.savetxt('test_csv.csv', large_array, delimiter=',')
load_time_csv = time.time() - start

start = time.time()
_ = np.loadtxt('test_csv.csv', delimiter=',')
save_time_csv = time.time() - start

print("格式\t保存时间(秒)\t加载时间(秒)")
print(f"NPY\t{save_time_npy:.4f}\t\t{load_time_npy:.4f}")
print(f"NPZ\t{save_time_npz:.4f}\t\t{load_time_npz:.4f}")
print(f"CSV\t{save_time_csv:.4f}\t\t{load_time_csv:.4f}")

# 清理测试文件
import os
for f in ['test_npy.npy', 'test_npz.npz', 'test_csv.csv']:
    os.remove(f)


# 错误处理示例
try:
    data = np.load('nonexistent_file.npy')
except FileNotFoundError as e:
    print(f"文件未找到错误: {e}")
    # 创建默认数据或采取其他措施
    data = np.zeros((10, 10))
except Exception as e:
    print(f"其他错误: {e}")
    data = np.zeros((10, 10))

# 最佳实践：使用上下文管理器确保文件正确关闭
with open('data.bin', 'wb') as f:
    arr1.tofile(f)

# 最佳实践：检查文件是否存在
import os
if os.path.exists('data.bin'):
    with open('data.bin', 'rb') as f:
        data = np.fromfile(f, dtype=arr1.dtype)
        data = data.reshape(arr1.shape)
else:
    print("文件不存在，创建新数据")
    data = np.zeros((10, 10))

# 最佳实践：验证加载的数据
assert data.shape == arr1.shape, f"形状不匹配: {data.shape} != {arr1.shape}"
assert data.dtype == arr1.dtype, f"类型不匹配: {data.dtype} != {arr1.dtype}"
print("数据验证通过")